/**
 *   Copyright (c) fanguangping. All rights reserved.
 *   The use and distribution terms for this software are covered by the
 *   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
 *   which can be found in the file epl-v10.html at the root of this distribution.
 *   By using this software in any fashion, you are agreeing to be bound by
 * 	 the terms of this license.
 *   You must not remove this notice, or any other, from this software.
 **/
package org.jfunny.core.sys;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jfunny.core.JFunny;
import org.jfunny.core.meta.Mapping;
import org.jfunny.core.meta.Namespace;
//import org.jfunny.core.meta.Protocol;
import org.jfunny.core.util.FileUtil;
import org.jfunny.core.util.StringUtil;

import clojure.lang.RT;

/**
 * 
 * @author fanguangping
 *
 */
public class SysLoader {
	//global settings
	public static Map<Namespace, List<Mapping>> MAPPINGS = null;
	public static Set<String> FUNCTIONS = null;
	//public static Map<Namespace, List<Protocol>> PROTOCOLS = null;
	
	//当前命名空间
	public static Namespace currentNamespace = null;

	public static void setCurrentNamespace(String namespace) {
		currentNamespace = Namespace.findNamespace(JFunny.allNamespace, namespace);
	}
	
	public static Namespace findNamespace(String namespace) {
		return Namespace.findNamespace(JFunny.usedNamespace, namespace);
	}
	
	public static void load() throws Exception {
		MAPPINGS = new HashMap<Namespace, List<Mapping>>();
		FUNCTIONS = new HashSet<String>();
		//PROTOCOLS = new HashMap<Namespace, List<Protocol>>();

		//加入系统命名空间
		File sysTemplate = new File(SysProperties.SYS_TEMPLATE_PATH);
		String template = FileUtil.readTxt(SysProperties.SYS_TEMPLATE_PATH);
		Namespace sysNamespace = new Namespace(SysProperties.SYS_NAMESPACE);
		sysNamespace.setFile(sysTemplate);
		sysNamespace.setSource(template);
		sysNamespace.setTemplateSpace(true);
		JFunny.allNamespace.add(sysNamespace);
		JFunny.usedNamespace.add(sysNamespace);

		//加载系统模板
		MAPPINGS.put(sysNamespace, parseTemplate(sysNamespace.getSource()));

		//加载核心模板命名空间
		File coreTpl = new File(SysProperties.CORE_TEMPLATE_PATH);
		String core = FileUtil.readTxt(SysProperties.CORE_TEMPLATE_PATH);
		Namespace coreNs = new Namespace(SysProperties.CORE_NAMESPACE);
		coreNs.setFile(coreTpl);
		coreNs.setSource(core);
		coreNs.setTemplateSpace(true);
		JFunny.allNamespace.add(coreNs);
		JFunny.usedNamespace.add(coreNs);

		RT.init();
	}
	
	public static boolean loaded() {
		return (MAPPINGS != null);
	}

	public static List<Mapping> getSysMappings() {
		Namespace sysNs = Namespace.findNamespace(MAPPINGS.keySet(), SysProperties.SYS_NAMESPACE);
		return MAPPINGS.get(sysNs);
	}

	public static List<Mapping> getAllMappings() {
		List<Mapping> mappings = new ArrayList<Mapping>();
		for (Namespace ns : JFunny.usedNamespace) {
			List<Mapping> nsMapping = MAPPINGS.get(ns);
			if (nsMapping != null) {
				mappings.addAll(nsMapping);
			}
		}

		return mappings;
	}

	public static List<Mapping> getUsedMappings(Namespace namespace) {
		if (namespace == null) {
			return getAllMappings();
		}

		List<Mapping> mappings = new ArrayList<Mapping>();

		List<Mapping> nsMapping = MAPPINGS.get(namespace);
		if (nsMapping != null) {
			mappings.addAll(nsMapping);
		}

		nsMapping = MAPPINGS.get(Namespace.findNamespace(MAPPINGS.keySet(), SysProperties.SYS_NAMESPACE));
		if (nsMapping != null) {
			mappings.addAll(nsMapping);
		}

		nsMapping = MAPPINGS.get(Namespace.findNamespace(MAPPINGS.keySet(), SysProperties.CORE_NAMESPACE));
		if (nsMapping != null) {
			mappings.addAll(nsMapping);
		}

		for (Namespace ns : namespace.getUsed()) {
			nsMapping = MAPPINGS.get(ns);
			if (nsMapping != null) {
				mappings.addAll(nsMapping);
			}
		}

		return mappings;
	}
	
	/**
	 * 目前系统模板由 "statement:" 和 "->" 作为分隔符
	 * @return
	 */
	private static List<Mapping> parseTemplate(String template) {
		List<Mapping> statements = new ArrayList<Mapping>();

		String[] srcs = StringUtil.removeComments(template, "$").split("statement:");
		for (String src : srcs) {
			String trimSrc = (src == null) ? null : src.trim();
			if (trimSrc != null && !"".equals(trimSrc)) {
				String[] trimSrcs = trimSrc.split("->");

				String key = trimSrcs[0].trim();
				String value = trimSrcs[1].trim();
				Mapping mapping = new Mapping(null, key, value, true);

				statements.add(mapping);
			}
		}

		return statements;
	}
}
